package com.voe;

import com.voe.common.CodecInst;
import com.voe.common.OutputParam;
import com.voe.common.PayloadFrequencies;
import com.voe.common.ReturnValue;
import com.voe.common.Utility;
import com.voe.common.VadModes;

/**This sub-API supports the following functionalities:<br/>
*<br/>
*- Support of non-default codecs (e.g. iLBC, iSAC, etc.).<br/>
*- Voice Activity Detection (VAD) on a per channel basis.<br/>
*- Possibility to specify how to map received payload types to codecs.<br/>
*<br/>
*Usage example, omitting error checking:<br/>
*<br/>
*VoiceEngine voe = VoiceEngine.createInterface();<br/>
*VoEBase base = VoEBase.createInterface(voe);<br/>
*VoECodec codec = VoECodec.createInterface(voe);<br/>
*base.init();<br/>
*int num_of_codecs = codec.numOfCodecs();<br/>
*...<br/>
*base.terminate();<br/>
*base.release();<br/>
*codec.release();<br/>
*voe.release();<br/>
*/
public class VoECodec {
	
	//[start] apis

	public static VoECodec createInstance(VoiceEngine voiceEngine) {

		long p = GetInterface(voiceEngine._p);
		if(p != 0)
			return new VoECodec(p);
		return null;
	}

	public void release() {
		if (_p != 0) {
			Release(_p);
		}
	}
	
	/** Gets the number of supported codecs.
	 */
	public int numOfCodecs() {
		return NumOfCodecs(_p);
	}

	/** Get the |codec| information for a specified list |index|.
	 */
	public int getCodec(int index, ReturnValue<CodecInst> codec) {
		OutputParam output = new OutputParam();
		int result = GetCodec(_p, index, output);
		if(result == 0) {
			codec.setValue(Utility.convert(output));
		}
		return result;
	}

	/** Sets the |codec| for the |channel| to be used for sending.
	 */
	public int setSendCodec(int channel, CodecInst codec) {
		return SetSendCodec(_p, channel, codec);
	}

	/** Gets the |codec| parameters for the sending codec on a specified<br/>
	 *  |channel|.
	 */
	public int getSendCodec(int channel, ReturnValue<CodecInst> codec) {
		OutputParam output = new OutputParam();
		int result = GetSendCodec(_p, channel, output);
		if(result == 0) {
			codec.setValue(Utility.convert(output));
		}
		return result;
	}

	/** Sets the |codec| as secondary codec for |channel|. Registering a<br/>
	 *  secondary send codec enables dual-streaming. In dual-streaming mode,<br/>
	 *  payloads of the primary and the secondary codecs are packed in RED<br/>
	 *  payloads with |red_payload_type| as payload type. The Secondary codec<br/>
	 *  MUST have the same sampling rate as the primary codec, otherwise the<br/>
	 *  codec cannot be registered and -1 is returned. This method fails if a<br/>
	 *  primary codec is not yet set.
	 */
	public int setSecondarySendCodec(int channel, CodecInst codec, int red_payload_type) {
		return SetSecondarySendCodec(_p, channel, codec, red_payload_type);
	}

	/** Removes the secondary codec from |channel|. This will terminate<br/>
	 *  dual-streaming.
	 */
	public int removeSecondarySendCodec(int channel) {
		return RemoveSecondarySendCodec(_p, channel);
	}

	/** Gets |codec| which is used as secondary codec in |channel|.
	 */
	public int getSecondarySendCodec(int channel, ReturnValue<CodecInst> codec) {
		OutputParam output = new OutputParam();
		int result = GetSecondarySendCodec(_p, channel, output);
		if(result == 0) {
			codec.setValue(Utility.convert(output));
		}
		return result;
	}

	/** Gets the currently received |codec| for a specific |channel|.
	 */
	public int getRecCodec(int channel, ReturnValue<CodecInst> codec) {
		OutputParam output = new OutputParam();
		int result = GetRecCodec(_p, channel, output);
		if (result == 0) {
			codec.setValue(Utility.convert(output));
		}
		return result;
	}

	/** Sets the initial values of target rate and frame size for iSAC<br/>
	 *  for a specified |channel|. This API is only valid if iSAC is setup<br/>
	 *  to run in channel-adaptive mode
	 */
	public int setISACInitTargetRate(int channel, int rateBps, boolean useFixedFrameSize) {
		return SetISACInitTargetRate(_p, channel, rateBps, useFixedFrameSize);
	}

	/** Sets the initial values of target rate and frame size for iSAC<br/>
	 *  for a specified |channel|. This API is only valid if iSAC is setup<br/>
	 *  to run in channel-adaptive mode
	 */
	public int setISACInitTargetRate(int channel, int rateBps) {
		return setISACInitTargetRate(channel, rateBps, false);
	}

	/** Sets the maximum allowed iSAC rate which the codec may not exceed<br/>
	 *  for a single packet for the specified |channel|. The maximum rate is<br/>
	 *  defined as payload size per frame size in bits per second.
	 */
	public int setISACMaxRate(int channel, int rateBps) {
		return SetISACMaxRate(_p, channel, rateBps);
	}


	/** Sets the maximum allowed iSAC payload size for a specified |channel|.<br/>
	 *  The maximum value is set independently of the frame size, i.e.<br/>
	 *  30 ms and 60 ms packets have the same limit.
	 */
	public int setISACMaxPayloadSize(int channel, int sizeBytes) {
		return SetISACMaxPayloadSize(_p, channel, sizeBytes);
	}

	/** Sets the dynamic payload type number for a particular |codec| or<br/>
	 *  disables (ignores) a codec for receiving. For instance, when receiving<br/>
	 *  an invite from a SIP-based client, this function can be used to change<br/>
	 *  the dynamic payload type number to match that in the INVITE SDP-<br/>
	 *  message. The utilized parameters in the |codec| structure are:<br/>
	 *  plname, plfreq, pltype and channels.
	 */
	public int setRecPayloadType(int channel, CodecInst codec) {
		return SetRecPayloadType(_p, channel, codec);
	}

	/** Gets the actual payload type that is set for receiving a |codec| on a<br/>
	 *  |channel|. The value it retrieves will either be the default payload<br/>
	 *  type, or a value earlier set with SetRecPayloadType().
	 */
	public int getRecPayloadType(int channel, ReturnValue<CodecInst> codec) {
		OutputParam output = new OutputParam();
		int result = GetRecPayloadType(_p, channel, output);
		if(result == 0) {
			codec.setValue(Utility.convert(output));
		}
		return result;
	}

	/** Sets the payload |type| for the sending of SID-frames with background<br/>
	 *  noise estimation during silence periods detected by the VAD.
	 */
	public int setSendCNPayloadType(int channel, int type, PayloadFrequencies frequency) {
		return SetSendCNPayloadType(_p, channel, type, frequency.getValue());
	}

	/** Sets the payload |type| for the sending of SID-frames with background<br/>
	 *  noise estimation during silence periods detected by the VAD.
	 */
	public int setSendCNPayloadType(int channel, int type) {
		return setSendCNPayloadType(channel, type, PayloadFrequencies.kFreq16000Hz);
	}

	/** Sets the VAD/DTX (silence suppression) status and |mode| for a<br/>
	 *  specified |channel|. Disabling VAD (through |enable|) will also disable<br/>
	 *  DTX; it is not necessary to explictly set |disableDTX| in this case.
	 */
	public int setVADStatus(int channel, boolean enable, VadModes mode, boolean disableDTX) {
		return SetVADStatus(_p, channel, enable, mode.getValue(), disableDTX);
	}

	/** Sets the VAD/DTX (silence suppression) status and |mode| for a<br/>
	 *  specified |channel|. Disabling VAD (through |enable|) will also disable<br/>
	 *  DTX; it is not necessary to explictly set |disableDTX| in this case.
	 */
	public int setVADStatus(int channel, boolean enable, VadModes mode) {
		return setVADStatus(channel, enable, mode, false);
	}

	/** Sets the VAD/DTX (silence suppression) status and |mode| for a<br/>
	 *  specified |channel|. Disabling VAD (through |enable|) will also disable<br/>
	 *  DTX; it is not necessary to explictly set |disableDTX| in this case.
	 */
	public int setVADStatus(int channel, boolean enable) {
		return setVADStatus(channel, enable, VadModes.kVadConventional, false);
	}

	/** Gets the VAD/DTX status and |mode| for a specified |channel|.
	 */
	public int getVADStatus(int channel, ReturnValue<Boolean> enabled, 
			ReturnValue<VadModes> mode, ReturnValue<Boolean> disabledDTX) {
		OutputParam output = new OutputParam();
		int result = GetVADStatus(_p, channel, output);
		if(result == 0) {
			enabled.setValue((Boolean)output.getObject()[0]);
			mode.setValue(VadModes.fromValue((Integer)output.getObject()[1]));
			disabledDTX.setValue((Boolean)output.getObject()[2]);
		}
		return result;
	}
	

	protected VoECodec(long p) {
		_p = p;
	}

	protected long _p;
	
	//[end]
	
	
	
	
	
	
	

	// [start] jni api

	// Factory for the VoECodec sub-API. Increases an internal
	// reference counter if successful. Returns NULL if the API is not
	// supported or if construction fails.
	private static native long GetInterface(long p_voiceEngine);

	// Releases the VoECodec sub-API and decreases an internal
	// reference counter. Returns the new reference count. This value should
	// be zero for all sub-API:s before the VoiceEngine object can be safely
	// deleted.
	private static native int Release(long p_VoECodec);

	// Gets the number of supported codecs.
	private static native int NumOfCodecs(long p_VoECodec);

	// Get the |codec| information for a specified list |index|.
	private static native int GetCodec(long p_VoECodec, int index,
			OutputParam codec);

	// Sets the |codec| for the |channel| to be used for sending.
	private static native int SetSendCodec(long p_VoECodec, int channel,
			CodecInst codec);

	// Gets the |codec| parameters for the sending codec on a specified
	// |channel|.
	private static native int GetSendCodec(long p_VoECodec, int channel,
			OutputParam codec);

	// Sets the |codec| as secondary codec for |channel|. Registering a
	// secondary send codec enables dual-streaming. In dual-streaming mode,
	// payloads of the primary and the secondary codecs are packed in RED
	// payloads with |red_payload_type| as payload type. The Secondary codec
	// MUST have the same sampling rate as the primary codec, otherwise the
	// codec cannot be registered and -1 is returned. This method fails if a
	// primary codec is not yet set.
	private static native int SetSecondarySendCodec(long p_VoECodec,
			int channel, CodecInst codec, int red_payload_type);

	// Removes the secondary codec from |channel|. This will terminate
	// dual-streaming.
	private static native int RemoveSecondarySendCodec(long p_VoECodec,
			int channel);

	// Gets |codec| which is used as secondary codec in |channel|.
	private static native int GetSecondarySendCodec(long p_VoECodec,
			int channel, OutputParam codec);

	// Gets the currently received |codec| for a specific |channel|.
	private static native int GetRecCodec(long p_VoECodec, int channel,
			OutputParam codec);

	// Sets the initial values of target rate and frame size for iSAC
	// for a specified |channel|. This API is only valid if iSAC is setup
	// to run in channel-adaptive mode
	private static native int SetISACInitTargetRate(long p_VoECodec,
			int channel, int rateBps, boolean useFixedFrameSize);

	// Sets the maximum allowed iSAC rate which the codec may not exceed
	// for a single packet for the specified |channel|. The maximum rate is
	// defined as payload size per frame size in bits per second.
	private static native int SetISACMaxRate(long p_VoECodec, int channel,
			int rateBps);

	// Sets the maximum allowed iSAC payload size for a specified |channel|.
	// The maximum value is set independently of the frame size, i.e.
	// 30 ms and 60 ms packets have the same limit.
	private static native int SetISACMaxPayloadSize(long p_VoECodec,
			int channel, int sizeBytes);

	// Sets the dynamic payload type number for a particular |codec| or
	// disables (ignores) a codec for receiving. For instance, when receiving
	// an invite from a SIP-based client, this function can be used to change
	// the dynamic payload type number to match that in the INVITE SDP-
	// message. The utilized parameters in the |codec| structure are:
	// plname, plfreq, pltype and channels.
	private static native int SetRecPayloadType(long p_VoECodec, int channel,
			CodecInst codec);

	// Gets the actual payload type that is set for receiving a |codec| on a
	// |channel|. The value it retrieves will either be the default payload
	// type, or a value earlier set with SetRecPayloadType().
	private static native int GetRecPayloadType(long p_VoECodec, int channel,
			OutputParam codec);

	// Sets the payload |type| for the sending of SID-frames with background
	// noise estimation during silence periods detected by the VAD.
	private static native int SetSendCNPayloadType(long p_VoECodec,
			int channel, int type, int frequency);

	// Sets the VAD/DTX (silence suppression) status and |mode| for a
	// specified |channel|. Disabling VAD (through |enable|) will also disable
	// DTX; it is not necessary to explictly set |disableDTX| in this case.
	private static native int SetVADStatus(long p_VoECodec, int channel,
			boolean enable, int mode, boolean disableDTX);

	// Gets the VAD/DTX status and |mode| for a specified |channel|.
	private static native int GetVADStatus(long p_VoECodec, int channel,
			OutputParam param);

	// [end]
}
